﻿#include "OperatorsJunctionArea.h"

#include "PickDataProvider/GUIPickInfo.h"
#include "PickDataProvider/PickedDataProvider.h"
#include "PickDataProvider/PickedData.h"
#include "GUIDialog/GUIJunctionDialog/SEAAreaJunctionDialog.h"

#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscNodeList.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysCavity.h"

#include "OperatorsInterface/GraphEventOperator.h"
#include "updateBrowserTable.h"

#include <QMessageBox>

namespace ModelOper
{
    bool OperatorsJunctionArea::execGUI()
    {
        //获取离散数据
        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (discModel == nullptr)return false;

        if (_senderName == "actionCreateJunctionArea") {
            GraphData::PickedDataProvider* provider = GraphData::PickedDataProvider::getInstance();
            if (provider == nullptr)return false;
            //清除拾取对象所有的连接
            QObject::disconnect(provider, SIGNAL(sig_pickedOver()), nullptr, nullptr);

            GUI::GUIPickInfoStru pickStr;
            pickStr._pickObjType = GUI::GUIPickInfo::PickObjType::POBJSEAShellAndCavity;
            pickStr._pickMethod = GUI::GUIPickInfo::PickMethod::PMIndividually;
            GUI::GUIPickInfo::ClearPickInfo();
            GUI::GUIPickInfo::SetPickInfo(pickStr);

            connect(provider, SIGNAL(sig_pickedOver()), this, SLOT(slotPickOverEvent()));
        }
        else if (_senderName == "actionEditJunctionArea") {
            int objID = -1;
            this->argValue(objID_String, objID);
            GUI::SEAAreaJunctionDialog* dialog = new GUI::SEAAreaJunctionDialog(objID, this, false);
            dialog->show();
        }
        else if (_senderName == "actionDeleteBatchArea") {
            if (discModel->getJunctionManager()) {
                QList<Acoustics::FITKAbstractJunction*> seaPointJunList =
                    discModel->getJunctionManager()->getJointsByType(Acoustics::FITKAbstractJunction::JunctionType::SEAAreaJunction);
                for (Acoustics::FITKAbstractJunction* seaPointJun : seaPointJunList) {
                    discModel->getJunctionManager()->removeDataObj(seaPointJun);
                }
            }
            EventOper::GraphEventOperator* operGraph = FITKOPERREPO->getOperatorT<EventOper::GraphEventOperator>("GraphPreprocess");
            if (operGraph) {
                operGraph->updateJunctions();
            }
        }
        return false;
    }

    bool OperatorsJunctionArea::execProfession()
    {
        int objId = -1;
        this->argValue(objID_String, objId);

        // Added by ChengHaotian 刷新可视化对象。
        //@{
        EventOper::GraphEventOperator* operGraph = FITKOPERREPO->getOperatorT<EventOper::GraphEventOperator>("GraphPreprocess");
        if (operGraph)
        {
            operGraph->updateGraph(objId);
        }
        //@}

        //更新表格
        ModelOper::updateBrowserTable();

        return false;
    }

    void OperatorsJunctionArea::slotPickOverEvent()
    {
        GraphData::PickedDataProvider* provider = GraphData::PickedDataProvider::getInstance();
        if (provider == nullptr)return;
        disconnect(provider, SIGNAL(sig_pickedOver()), this, SLOT(slotPickOverEvent()));

        QList<GraphData::PickedData*> pickList = provider->getPickedList();
        QList<int> idList = {};
        for (GraphData::PickedData* pickData : pickList) {
            if (pickData == nullptr)continue;
            idList.append(pickData->getPickedDataObjId());
        }
        GUI::GUIPickInfo::ClearPickInfo();

        if (pickSEAValueIsValidity(idList) == false)return;
        
        GUI::SEAAreaJunctionDialog* dialog = new GUI::SEAAreaJunctionDialog(-1, this, true);
        dialog->setSubSysIDs(idList);
        dialog->show();
    }

    bool OperatorsJunctionArea::pickSEAValueIsValidity(const QList<int>& subSysIds)
    {
        //信息输出局部函数
        auto message = [&](const QString& message) {
            QMessageBox box(QMessageBox::Warning, "", QString(message), QMessageBox::Ok);
            box.exec();
        };

        //选取少于两个
        if (subSysIds.size() < 2) {
            message(QString(tr("Too few select picked!")));
            return false;
        }

        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (discModel == nullptr) {
            message(QString(tr("Acoustics model nullptr!")));
            return false;
        };
        Acoustics::FITKAcousticsSEAModel* SEAModel = discModel->getSEAModel();
        if (SEAModel == nullptr && SEAModel->getSEASubSysManager() == nullptr) {
            message(QString(tr("SEA model nullptr!")));
            return false;
        }

        int cavityNum = 0, shellNum = 0;
        QList<Acoustics::FITKAbstractSEASubSys*> cavitySubSysList = {};
        int shellID = 0;
        for (int subSysID : subSysIds) {
            Acoustics::FITKAbstractSEASubSys* subSys = SEAModel->getSEASubSysManager()->getDataByID(subSysID);
            if (subSys == nullptr)continue;
            auto type = subSys->getSEASubSysType();
            switch (type) {
            case Acoustics::FITKAbstractSEASubSys::SEAFlatPlate:
            case Acoustics::FITKAbstractSEASubSys::SEASinglyCurvedShell:
            case Acoustics::FITKAbstractSEASubSys::SEADoublyCurvedShell:
            case Acoustics::FITKAbstractSEASubSys::SEACylinderShell: {
                shellNum++;
                shellID = subSysID;
                break;
            }
            case Acoustics::FITKAbstractSEASubSys::SEACavity: {
                cavityNum++;
                cavitySubSysList.append(subSys);
                break;
            }
            }
        }

        if (cavityNum < 1 || cavityNum > 2 || shellNum != 1) {
            message(QString(tr("Supports only cavity - plate/shell, cavity - plate/shell - cavity!")));
            return false;
        }

        //判断板是否被声腔使用
        for (auto subSys : cavitySubSysList) {
            Acoustics::FITKSEASubSysCavity* cavity = dynamic_cast<Acoustics::FITKSEASubSysCavity*>(subSys);
            if (cavity == nullptr)continue;
            if (cavity->getShellIndex(shellID) == -1) {
                message(QString(tr("The plate/shell was not used by the cavity!")));
                return false;
            }
        }
        return true;
    }
}